package com.fany.filesearcher;

import android.graphics.Bitmap;
import com.fany.utils.ConfigUtils;
import com.fany.utils.FileHelper;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * Created by fany on 14-1-22.
 */
public class FileScanner
{
    private static final int SegmentCount = 1000;

    private static FileScanner _instance = new FileScanner();

    private List<String> _records;
    private Stack<String> _roots;
    private HashSet<String> _softlinkCaches;
    private boolean _isScaning;
    private boolean _isSegmentCompleted;
    private boolean _isCompleted;
    private boolean _isInterrupted;
    private int _lastFileCount;

    public static FileScanner instance()
    {
        return _instance;
    }

    public void beginScan(String[] roots)
    {
        if (_isScaning)
        {
            return;
        }
        _isScaning = true;
        _lastFileCount = 0;
        _records = new ArrayList<String>();
        _roots = new Stack<String>();
        _softlinkCaches = new HashSet<String>();
        _isCompleted = false;
        Arrays.sort(roots);
        for (int i = roots.length - 1; i >= 0; i--)
        {
            if (i > 0)
            {
                String parent = FileHelper.extractDirectoryName(roots[i]);
                boolean isChild = false;
                for (int index = i - 1; index >= 0; index--)
                {
                    if (parent.contains(roots[index]))
                    {
                        isChild = true;
                        break;
                    }
                }
                if(isChild){
                    continue;
                }
            }
            _roots.push(roots[i]);
        }
    }

    public void endScan()
    {
        _records.clear();
        _records = null;
        _isScaning = false;
    }

    public List<String> scanFiles(boolean recursion)
    {
        try
        {
            _lastFileCount += _records.size();
            _records.clear();
            _isSegmentCompleted = false;
            while (!_isCompleted && !_isSegmentCompleted)
            {
                if (_roots.empty())
                {
                    _isCompleted = true;
                    break;
                }
                File file = new File(_roots.pop());
                doSearchFiles(file, recursion);
            }
        }
        catch (IllegalArgumentException ignored)
        {
        }
        return _records;
    }

    public boolean isCompleted()
    {
        return _isCompleted;
    }

    public boolean isInterrupted()
    {
        return _isInterrupted;
    }

    private void doSearchFiles(File baseFile, boolean recursion)
    {
        if (_records.size() >= SegmentCount)
        {
            _isSegmentCompleted = true;
        }
        if (_records.size() + _lastFileCount >= ConfigUtils.getInstance().getCacheCapacity())
        {
            _roots.clear();
            return;
        }
        _records.add(baseFile.getAbsolutePath());
        File[] childFiles = baseFile.listFiles();
        if (childFiles == null)
        {
            return;
        }
        for (File file : childFiles)
        {
            if (file.isDirectory())
            {
                try
                {
                    String realPath = file.getCanonicalPath();
                    if (realPath.equals(file.getAbsolutePath()))
                    {
                        if (recursion)
                        {
                            _roots.push(file.getAbsolutePath());
                        }
                    }
                    else
                    {
                        if (_softlinkCaches.contains(realPath))
                        {
                            _records.add(file.getAbsolutePath());
                        }
                        else
                        {
                            if (recursion)
                            {
                                _roots.push(file.getAbsolutePath());
                            }
                            _softlinkCaches.add(realPath);
                        }
                    }
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            else
            {
                _records.add(file.getAbsolutePath());
            }
        }
    }

    public void interrupt()
    {
        _isCompleted = true;
        _isSegmentCompleted = true;
        _isInterrupted = true;
    }

    public int getScannedCount()
    {
        if (_isScaning && (_records != null))
        {
            return _records.size() + _lastFileCount;
        }
        else
        {
            return -1;
        }
    }
}